<template>
  <div class="flv-player"
       ref="ruienVideoPlayer"
       :style="fixedStyle">
    <video :id='videoId'
           style="display:none"
           class="flv-vidoe"
           controls></video>
    <div class="flv-video-box"
         v-loading="loading"
         @mousemove.capture="showControls"
         @mouseout.capture="hideControls">
      <canvas :id="canvasId"
              :width="boxWidth"
              :height="boxHeight"></canvas>
      <!-- 视频控件 -->
      <transition name="fade">
        <div class="controls"
             v-show="show">
          <div class="controls-btn">
            <div class="controls-btn-left">
              <span class="live">LIVE</span>
            </div>
            <div class="controls-btn-right">
              <div class="iconfont icon-pic"
                   @click="screenshot"></div>
              <div class="iconfont icon-full"
                   @click="fullscreenHandle"></div>
            </div>
          </div>
        </div>
      </transition>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
import mpegts from 'mpegts.js'
import screenfull from 'screenfull'
const elementResizeDetectorMaker = require('element-resize-detector')
export default {
  props: {
    url: {
      type: String,
      default: ''
    }
  },
  mounted () {
    window.addEventListener('resize', this.monitorFullScreen)
    this.videoId = `video-${this.uuid()}`
    this.canvasId = `canvas-${this.uuid()}`
    this.$nextTick(() => {
      const erd = elementResizeDetectorMaker()
      this.erd = erd
      erd.listenTo(this.$refs.ruienVideoPlayer, this.setVideoCanvasSize)
    })
  },
  beforeDestroy () {
    this.erd.removeListener(this.$refs.ruienVideoPlayer, this.setVideoCanvasSize)
    this.reset()
  },
  data () {
    return {
      loading: true,
      boxHeight: 300,
      boxWidth: 500,
      controlsTimer: 0,
      show: true,
      videoId: '',
      canvasId: '',
      player: null,
      timer: 0,
      vidoeEl: '',
      erd: '',
      requestAnimationFrameTimer: 0,
      ruienVideoPlayerRef: '',
      fixedStyle: {
        'position': 'relative',
        'z-index': 0
      }
    }
  },
  watch: {
    url (newValue) {
      if (newValue === '') {
        this.reset()
        return false
      }
      this.initVideo()
    }
  },
  methods: {
    uuid () {
      let s = []
      let hexDigits = '0123456789abcdef'
      for (let i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
      }
      s[14] = '4'
      s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1)
      s[8] = s[13] = s[18] = s[23] = '-'

      let uuid = s.join('')
      return uuid
    },
    initVideo () {
      this.reset()
      const element = document.getElementById(this.videoId)
      const ruienVideoPlayerRef = this.$refs.ruienVideoPlayer
      this.boxHeight = ruienVideoPlayerRef.clientHeight
      this.boxWidth = ruienVideoPlayerRef.clientWidth
      element.volume = 0
      const player = mpegts.createPlayer({
        type: 'mse',
        url: this.url
      }, {
        isLive: true,
        liveBufferLatencyChasing: true,
        withCredentials: false,
        enableWorker: true,
        lazyLoadMaxDuration: 3 * 60,
        seekType: 'range'
      })
      this.player = player
      this.vidoeEl = element
      player.attachMediaElement(element)
      player.load()
      element.addEventListener('loadeddata', this.loadeddataFn)
      this.ruienVideoPlayerRef = ruienVideoPlayerRef
    },
    loadeddataFn () {
      this.loading = false
      this.player.play()
      this.videoMappingCanvas()
    },
    // 将视频内容转到画布上
    videoMappingCanvas () {
      const videoCanvasRef = document.getElementById(this.canvasId)
      this.ctx = videoCanvasRef.getContext('2d')
      this.ctx.drawImage(this.player._mediaElement, 0, 0, this.boxWidth, this.boxHeight)
      this.requestAnimationFrameTimer = requestAnimationFrame(this.videoMappingCanvas)
    },
    // TODO 全屏
    fullscreenHandle () {
      if (!screenfull.isFullscreen) {
        clearTimeout(this.timer)
        screenfull.toggle().then(() => {
          this.fixedStyle = {
            'position': 'fixed',
            'z-index': 99999999
          }
          this.timer = setTimeout(() => {
            clearTimeout(this.timer)
            // this.setVideoCanvasSize(this.ruienVideoPlayerRef)
          }, 100)
        })
      } else {
        screenfull.exit().then(() => {
          this.fixedStyle = {
            'position': 'relative',
            'z-index': 0
          }
          // this.setVideoCanvasSize()
        })
      }
    },
    // TODO 关闭全屏
    beforeClose () {
      // this.setVideoCanvasSize()
      this.fixedStyle = {
        position: 'relative'
      }
      if (screenfull.isFullscreen) {
        screenfull.exit()
      }
    },
    // TODO 监听是否为全屏状态
    monitorFullScreen () {
      if (screenfull.isEnabled) {
        screenfull.on('change', () => {
          if (!screenfull.isFullscreen) {
            this.beforeClose()
          }
        })
      }
    },
    // TODO 设置视频画布的大小
    setVideoCanvasSize (el) {
      const width = el.clientWidth
      const height = el.clientHeight
      this.boxWidth = width
      this.boxHeight = height
    },
    // TODO 显示控件
    showControls () {
      clearTimeout(this.controlsTimer)
      this.show = true
    },
    // TODO 隐藏控件
    hideControls () {
      clearTimeout(this.controlsTimer)
      this.controlsTimer = setTimeout(() => {
        this.show = false
      }, 300)
    },
    // TODO 截图
    screenshot () {
      this.$nextTick(() => {
        const canvas = document.getElementById(this.canvasId)
        canvas.width = this.boxWidth
        canvas.height = this.boxHeight
        let ctx = canvas.getContext('2d')
        ctx.drawImage(this.player._mediaElement, 0, 0, this.boxWidth, this.boxHeight)
        const png = canvas.toDataURL('image/png')
        this.getBlobUrl(png).then(res => {
          if (res.data === -1) {
            alert('图片转换失败')
            return false
          }
          const url = URL.createObjectURL(res.data)
          const a = document.createElement('a')
          a.setAttribute('href', url)
          a.download = this.getNewDate()
          a.click()
          URL.revokeObjectURL(url)
        })
      })
    },
    // TODO 获取当前时间
    getNewDate () {
      const date = new Date()
      const year = date.getFullYear()
      const month = date.getMonth() + 1
      const day = date.getDate()
      const h = date.getHours() > 9 ? date.getHours() : `0${date.getHours()}`
      const m = date.getMinutes() > 9 ? date.getMinutes() : `0${date.getMinutes()}`
      const s = date.getSeconds() > 9 ? date.getSeconds() : `0${date.getSeconds()}`

      return `${year}年${month}月${day}日 ${h}:${m}:${s}`
    },
    // 重置播放器
    reset () {
      if (typeof this.player !== 'undefined') {
        if (this.player !== null) {
          this.loading = true
          cancelAnimationFrame(this.requestAnimationFrameTimer)
          this.vidoeEl.removeEventListener('loadeddata', this.loadeddataFn)
          this.player.pause()
          this.player.unload()
          this.player.detachMediaElement()
          this.player.destroy()
          this.player = null
        }
      }
    },
    // TODO url 转 blob连接
    async getBlobUrl (url) {
      const res = await axios.get(url, {
        responseType: 'blob'
      })
      return res || { data: -1 }
    }
  }
}
</script>

<style lang="scss" scoped>
.flv-vidoe {
  position: absolute;
  top: 0;
  left: 0;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}
.flv-player {
  width: 100%;
  height: 100%;
  position: relative;
  top: 0;
  left: 0;
  .flv-video-box {
    position: relative;
    display: inline-block;
    .controls {
      position: absolute;
      bottom: 0;
      left: 0;
      width: 100%;
      background-color: rgba(19, 19, 19, 0.6);
      color: white;
      // background: linear-gradient(to top, #050505, transparent);
      text-align: left;
      margin-left: auto;
      margin-right: auto;
      z-index: 2;
      .controls-btn {
        width: 100%;
        height: 30px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        .controls-btn-left {
          position: relative;
          flex: 6;
          display: flex;
          justify-content: flex-start;
          align-items: center;
          padding: 10px;
          box-sizing: border-box;
          .live {
            position: relative;
            padding-left: 15px;
            &::after {
              content: "";
              width: 10px;
              height: 10px;
              border-radius: 10px;
              background-color: white;
              position: absolute;
              top: 4px;
              left: 0;
            }
          }
        }
        .controls-btn-right {
          flex: 5;
          display: flex;
          justify-content: flex-end;
          align-items: center;
          padding: 10px;
          box-sizing: border-box;
          > div {
            margin: 0 5px;
            cursor: pointer;
          }
        }
      }
    }
  }
}
</style>
